#include "LogicFriendModule.h"
#include "LogicService.h"

#include "base/core/com_define.h"
#include "base/core/os/time.h"
#include "base/core/Profiler.h"
#include "base/core/gamemath.h"
#include "Common/Utility/ServerTime.h"
#include "ProtoBuffer/AllProtocol.h"
#include "Access/CharacterDataSet.h"
#include "Character/PlayerMgr.h"
#include "Common/TableData/RoleBornCfg.h"
#include "Common/TableData/ItemItemCfg.h"
#include "Common/TableData/EquipEquipCfg.h"
#include "Common/TableData/RoleExpCfg.h"
#include "Common/Item/ItemMgr.h"
#include "Common/Utility/AccountUtility.h"
#include "Common/RelationDefine.h"
#include "Character/drop/DropMgr.h"
#include "LogicActivityModule.h"
#include "Duplicate/DuplicateMgr.h"
#include "Mail/GMailManager.h"
//#include "Common/Item/ItemMgr.h"
#include "Common/TableDataEx/ItemCfg.h"

#ifdef _MSC_VER
#pragma warning(disable:4100)
#pragma warning(disable:4244)
#pragma warning(disable:4102)
#endif

using namespace ProtoBuf;


LogicFriendModule::LogicFriendModule()
{

}

LogicFriendModule::~LogicFriendModule()
{

}


bool LogicFriendModule::Init()
{
	IMessageDispatch *pMessageDispatch = g_GetLogicService()->GetServiceMessageDispatch();
	if (nullptr == pMessageDispatch)
	{
		return false;
	}
	pMessageDispatch->registerClientHandler(EMODULE_ID_FRIEND, this);
	pMessageDispatch->registerServerHandler(EMODULE_ID_FRIEND, this);

	g_GetEvent()->Subscribe(dynamic_cast<IEventExecuteSink*>(this), EVENT_CREATURE_DEAD, 0, CREATURE_PLAYER, NULL);

	return true;
}

void LogicFriendModule::UnInit()
{
	IMessageDispatch *pMessageDispatch = g_GetLogicService()->GetServiceMessageDispatch();
	if (nullptr == pMessageDispatch)
	{
		return;
	}
	pMessageDispatch->unregisterClientHandler(EMODULE_ID_FRIEND);
	pMessageDispatch->unregisterServerHandler(EMODULE_ID_FRIEND);

	g_GetEvent()->UnSubscribeAll(this);
}

void LogicFriendModule::onClientMessage(uint32_t actionId, RECV_PACKAGE& package, uint64_t Id /* = 0 */)
{
	switch (actionId)
	{
	case CLIENT_TO_SERVER_TRACK_HATE:
	{
		OnTrackHateReq(Id, package);
	}
	break;
	default:
		break;
	}
	//package;
}

void LogicFriendModule::onServerMessage(uint32_t actionId, RECV_PACKAGE &package)
{
	switch (actionId)
	{
	case CENTER_SERVER_PROTOCOL_GET_PHYSICAL_TO_LOGIC:
	{
		OnWLGetPhyscialReq(package);
		break;
	}
	case CENTER_SERVER_PROTOCOL_GET_PHYSICAL_GIFT_TO_LOGIC:
	{
		OnWLGetPhysicalGiftReq(package);
		break;
	}
	case CENTER_SERVER_PROTOCOL_ADD_FRIEND_NOTIFY:
	{
		OnWLAddFriendReq(package);
		break;
	}
	case CEENER_SERVER_PROTOCOL_GIVE_PHYSICAL_GIFT:
	{
		OnWLGivePhyscialNotify(package);
		break;
	}
	case CENTER_TO_LOGIC_TRACK_ERROR:
	{
		OnWLTrackHateErrorNotify(package);
		break;
	}
	case CENTER_TO_LOGIC_TRACK_HATE:
	{
		OnWLTrackHateReq(package);
		break;
	}
	case SERVER_TO_CLIENT_COST_STH:
	{
		OnWLRelationCost(package);
		break;
	}
	case CENTER_TO_LOGIC_HANDSEL_ROSE:
	{
		OnWLHandselRoseReq(package);
		break;
	}
	case CENTER_TO_LOGIC_UPDATE_CHARM:
	{
		OnWLUpdateCharm(package);
		break;
	}
	case CENTER_TO_LOGIC_UPDATE_CLOSENESS:
	{
		OnWLUpdateCloseness(package);
		break;
	}
	default:
		break;
	}
}

void LogicFriendModule::OnExecute(uint16_t nEventID, uint64_t nSrcID, uint8_t bySrcType, void *pContext, int32_t nLen)
{
	switch (nEventID)
	{
	case EVENT_CREATURE_DEAD: //生物死亡
	{
		DieEvent dieEvent = *(DieEvent*)pContext;
		uint32_t sceneId = dieEvent.sceneId;
		Scene* pScene = g_GetSceneMgr()->GetScene(sceneId);
		if (nullptr == pScene)
			break;

		Player* pSrcPlayer = pScene->GetPlayer(nSrcID);
		if (nullptr == pSrcPlayer)
			break;

		Player* pDstPlayer = pScene->GetPlayer(dieEvent.killerCid);
		if (nullptr == pDstPlayer)
			break;

		//工会活动不允许击杀不准许加仇恨列表
		if (!g_GetGActivityMgr()->CanAddHateList(pSrcPlayer, pDstPlayer))
		{
			if (pScene->IsDynamic() || nullptr != g_GetDuplicateMgr()->GetDuplicate(sceneId))
				break;
		}
		
		GWAddHateReq addHateReq;
		addHateReq.set_srcid(nSrcID);
		addHateReq.set_dstid(dieEvent.killerCid);
		g_GetLogicService()->SendDataToCenter(EMODULE_ID_FRIEND, LOGIC_TO_CENTER_ADD_HATE, &addHateReq);
		break;
	}
	default:
		break;
	}

}

bool LogicFriendModule::OnWLGetPhyscialReq(RECV_PACKAGE &package)
{
	//修改 策划去掉了游戏体力这东西 这里改成添加礼包了
	ProtoBuf::WLGetPhyscialReq req;
	if (!req.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("WLGetPhyscialReq parse failed...");
		return false;
	}
	else
	{
		CharIDType playerID = req.playerid();
		Player* pPlayer = g_GetCreatureMgr()->GetPlayer(playerID);
		if (nullptr == pPlayer)
		{
			MMOLOG_FMT_ERROR("LogicFriendModule::OnWLGetPhyscialReq but player is nullptr playerId=%u", playerID);
			return false;
		}
		else
		{
			Part *pPackage = pPlayer->GetPart(PART_PACKAGE);
			if (nullptr == pPackage)
			{
				MMOLOG_FMT_ERROR("LogicFriendModule::OnWLGetPhyscialReq but pPackage part is nullptr playerId=%u", playerID);
				return false;
			}

			/*//增加礼包
			LIST_ITEM lstItem;
			SItem item;
			item.nItemID = RELATION_GIVE_GIFT_ID;
			item.nNum = 1;
			lstItem.push_back(item);
			pPackage->AddItem(lstItem);*/

			//增加礼包
			LIST_ITEM addItems;
			SItem item;
			item.nItemID = RELATION_GIVE_GIFT_ID;
			item.nNum = 1;
			addItems.push_back(item);
			VEC_ITEM_PROTO_EX vecProtoEx;
			vecProtoEx.clear();
			SItemCond itemCond;
			g_GetDropMgr()->GetItemCond(pPlayer, itemCond,EItemInitAttrType_NpcShop);
			g_GetItemMgr()->CreateItem(addItems, vecProtoEx, itemCond);
			SItemSourceParam soureParam;
			soureParam.source = S_FRIEND;
			if (!pPackage->AddItem(vecProtoEx, soureParam))
			{
				string mailTitle = "好友礼包";
				char mailContent[256];
				snprintf(mailContent, sizeof(mailContent), "背包空间不足,好友礼包转发至邮件！");
				g_GetGMailMgr()->SendSystemMail(pPlayer->GetId(), mailTitle, mailContent, 0, 0, 0, 0, 0, vecProtoEx);

				CollectNotifyError notify;
				notify.set_retcode(RET_RELATION_GIFT_TO_MAIL);
				pPlayer->SendDataToClient(EMODULE_ID_FRIEND, SERVER_TO_CLIENT_COLLECT_NOTIFY_ERROR, &notify);
			}
		}
	}

	return true;
}

bool LogicFriendModule::OnWLGetPhysicalGiftReq(RECV_PACKAGE &package)
{
	ProtoBuf::WLGetPhysicalGiftReq req;
	ProtoBuf::LCGetPhysicalGiftRsp rsp;
	if (!req.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("WLGetPhysicalGiftReq parse failed...");
		return false;
	}
	
	CharIDType playerID = req.playerid();
	Player* pPlayer = g_GetCreatureMgr()->GetPlayer(playerID);
	if (nullptr == pPlayer)
	{
		MMOLOG_FMT_ERROR("LogicFriendModule::OnWLGetPhysicalGiftReq but player is nullptr playerId=%u", playerID);
		return false;
	}
	
	Part *pPackage = pPlayer->GetPart(PART_PACKAGE);
	if (nullptr == pPackage)
	{
		MMOLOG_FMT_ERROR("LogicFriendModule::OnWLGetPhysicalGiftReq but pPackage part is nullptr playerId=%u", playerID);
		return false;
	}

	/*VEC_ITEM_PROTO_EX vecProtoEx;
	vecProtoEx.clear();
	int32_t gold = 0;
	int32_t diamond = 0;
	int32_t binddiamond = 0;
	BoxCondCfg boxCond;
	g_GetDropMgr()->GetBoxCond(pPlayer,boxCond);
	g_GetItemMgr()->CreateBoxDropItem(RELATION_FEEDBACK_GIFT_ID, vecProtoEx, gold, diamond, binddiamond, boxCond);
	if (vecProtoEx.size() > 0)
	{
		pPackage->AddItem(vecProtoEx, S_FRIEND);
		for (uint32_t i = 0; i < vecProtoEx.size(); i++)
		{
			rsp.add_goodid(vecProtoEx[i].item_id());
			rsp.add_goodnum(vecProtoEx[i].item_num());
		}
	}
	if (gold > 0)
	{
	pPlayer->AddSourceAttr(C_GOLD, gold, true, S_FRIEND);
	}
	if (diamond > 0)
	{
	pPlayer->AddSourceAttr(C_DIAMOND, diamond, true, S_FRIEND);
	}
	if (binddiamond > 0)
	{
	pPlayer->AddSourceAttr(C_DIAMOND_BIND, binddiamond, true, S_FRIEND);
	}
	*/

	LIST_ITEM addItems;
	SItem item;
	item.nItemID = RELATION_FEEDBACK_ITEM_ID;
	item.nNum = 1;
	item.byBind = (int8_t)EBindState::EBindState_no;
	addItems.push_back(item);
	SItemSourceParam sourceParam;
	sourceParam.source = S_FRIEND;
	if (!pPackage->AddItem(addItems, sourceParam))
	{
		VEC_ITEM_PROTO_EX vecProto;
		vecProto.clear();
		SItemCond itemCond;
		g_GetDropMgr()->GetItemCond(pPlayer, itemCond);
		if (g_GetItemMgr()->SetItemProtoInfo(addItems, vecProto, itemCond))
		{
			string strTopic = "好友回馈宝箱";
			string strContent = "包裹空间不足，好友回馈宝箱已通过邮件发送！";
			g_GetGMailMgr()->SendSystemMail(pPlayer->GetId(), strTopic, strContent, 0, 0, 0, 0, 0, vecProto);
		}
	}

	rsp.add_goodid(RELATION_FEEDBACK_ITEM_ID);
	rsp.add_goodnum(1);
	pPlayer->SendDataToClient(EMODULE_ID_FRIEND, LOGIC_TO_CLIENT_GET_PHYSICAL_GIFT, &rsp);

	return true;
}

bool LogicFriendModule::OnWLAddFriendReq(RECV_PACKAGE &package)
{
	ProtoBuf::WGNotifyAddFriend req;
	if (!req.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("WGNotifyAddFriend parse failed...");
		return false;
	}

	CharIDType charId = req.charid();
	Player* pPlayer = g_GetCreatureMgr()->GetPlayer(charId);
	if (nullptr == pPlayer)
	{
		MMOLOG_FMT_ERROR("LogicFriendModule::OnWLAddFriendReq but player is nullptr charId=%u", charId);
		return false;
	}

	if (req.operate_type() == 1)
	{
		//触发加好友事件
		FriendAddEvent addEvent;
		addEvent.num = req.addnum();
		g_GetEvent()->FireExecute(EVENT_ADD_FRIEND, pPlayer->GetCid(), pPlayer->CreatureKind(), (FriendAddEvent*)&addEvent, sizeof(addEvent));
	}
	else if (req.operate_type() == 2)
	{
		//击杀仇人事件
		g_GetEvent()->FireExecute(EVENT_KILL_ENEMY, pPlayer->GetCid(), pPlayer->CreatureKind(), nullptr, 0);
	}

	return true;
}

bool LogicFriendModule::OnWLGivePhyscialNotify(RECV_PACKAGE &package)
{
	ProtoBuf::WLPhysicalNotify req;
	if (!req.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("WLPhysicalNotify parse failed...");
		return false;
	}

	CharIDType charId = req.playerid();
	uint32_t times = req.times();

	Player* pPlayer = g_GetCreatureMgr()->GetPlayer(charId);
	if (nullptr == pPlayer)
	{
		MMOLOG_FMT_ERROR("LogicFriendModule::OnWLGivePhyscialNotify but player is nullptr charId=%u", charId);
		return false;
	}

	//触发好友送礼包事件
	FriendGiftEvent friendGiftEvent;
	friendGiftEvent.times = times;
	g_GetEvent()->FireExecute(EVENT_FRIEND_GIFT, pPlayer->GetCid(), pPlayer->CreatureKind(), (FriendGiftEvent*)&friendGiftEvent, sizeof(friendGiftEvent));

	return true;
}

bool LogicFriendModule::OnWLTrackHateReq(RECV_PACKAGE &package)
{
	ProtoBuf::TrackHateReq req;
	if (!req.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("OnWLTrackHateReq parse failed...");
		return false;
	}

	//如果角色不存在 再次通知中心服 此时角色有可能正在跳转场景
	CharIDType hateId = req.hateid();
	Player* pPlayer = g_GetCreatureMgr()->GetPlayer(hateId);
	if (nullptr == pPlayer)
	{
		g_GetLogicService()->SendDataToCenter(EMODULE_ID_FRIEND, LOGIC_TO_CENTER_TRACK_HATE, &req);
		return false;
	}

	ProtoBuf::GWTrackHateScuess trackHateSucess;
	trackHateSucess.set_ret(RET_SUCCESS);
	trackHateSucess.set_hateid(hateId);
	trackHateSucess.set_sceneid(pPlayer->GetMapId());
	trackHateSucess.set_charid(req.charid());

	if (pPlayer->GetScene()->IsUnion() || pPlayer->GetScene()->IsDynamic() || pPlayer->IsInJail() || nullptr != g_GetDuplicateMgr()->GetDuplicate(pPlayer->GetSceneId()))
	{
		trackHateSucess.set_ret(RET_RELATION_TRACK_HATE_ERROR);
		g_GetLogicService()->SendDataToCenter(EMODULE_ID_FRIEND, LOGIC_TO_CENTER_TRACK_SUCESS, &trackHateSucess);
		return true;
	}

	//成功通知
	Point3<float> pos = pPlayer->GetPos();
	Vector3PB* pCurpos = new Vector3PB();
	pCurpos->set_x(pos.x);
	pCurpos->set_y(pos.y);
	pCurpos->set_z(pos.z);
	trackHateSucess.set_allocated_dstpos(pCurpos);
	g_GetLogicService()->SendDataToCenter(EMODULE_ID_FRIEND, LOGIC_TO_CENTER_TRACK_SUCESS, &trackHateSucess);

	return true;
}

bool LogicFriendModule::OnWLTrackHateErrorNotify(RECV_PACKAGE &package)
{
	ProtoBuf::WGTrackHateError req;
	ProtoBuf::WCTrackHateRsp rsp;
	if (!req.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		LogErrFmtPrint("[logic] WGTrackHateError parse failed...");
		return false;
	}

	CharIDType charId = req.charid();
	//这种情况找不到就加不回物品了 因为此时该玩家也有可能在跳转场景
	Player *pPlayer = g_GetCreatureMgr()->GetPlayer(charId);
	if (nullptr == pPlayer)
	{
		LogErrFmtPrint("[logic] LogicFriendModule::OnWLTrackHateErrorNotify pPlayer is nullptr...charId:%llu", charId);
		return false;
	}

	/*Part *pPackage = pPlayer->GetPart(PART_PACKAGE);
	if (nullptr == pPackage)
	{
		MMOLOG_FMT_DEBUG("[logic] LogicFriendModule::OnWLTrackHateErrorNotify pPackage part is nullptr charId=%llu", charId);
		return false;
	}

	//如果失败需要将玩家的道具重新加回
	pPackage->AddItem(RELATION_TRACK_HATE_GOODID, 1, S_FRIEND);*/
	rsp.set_ret(req.ret());
	pPlayer->SendDataToClient(EMODULE_ID_FRIEND, ProtoBuf::SERVER_TO_CLIENT_TRACK_HATE, &rsp);
	return true;
}


bool LogicFriendModule::OnWLRelationCost(RECV_PACKAGE &package)
{
	ProtoBuf::GWRelationCostSth cost;
	if (!cost.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		LogErrFmtPrint("[logic] OnWLRelationCost parse failed...");
		return false;
	}

	Player *pPlayer = g_GetCreatureMgr()->GetPlayer(cost.charid());
	if (nullptr == pPlayer)
	{
		LogErrFmtPrint("[logic] LogicFriendModule::OnWLRelationCost pPlayer is nullptr...charId:%llu", cost.charid());
		return false;
	}

	Part *pPackage = pPlayer->GetPart(PART_PACKAGE);
	if (nullptr == pPackage)
	{
		LogErrFmtPrint("[logic] LogicFriendModule::OnWLRelationCost pPackage part is nullptr charId=%lu", cost.charid());
		return false;
	}
	SItemSourceParam soureParam;
	soureParam.source = S_FRIEND;
	pPackage->RemoveItem(cost.itemid(), cost.count(), soureParam);
	return true;
}

bool LogicFriendModule::OnWLHandselRoseReq(RECV_PACKAGE &package)
{
	ProtoBuf::C2LHandselRoseReq c2lHandselRoseReq;
	if (!c2lHandselRoseReq.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		LogErrFmtPrint("[logic] OnWLHandselRoseReq parse failed...");
		return false;
	}

	Player *pPlayer = g_GetCreatureMgr()->GetPlayer(c2lHandselRoseReq.charid());
	if (nullptr == pPlayer)
	{
		LogErrFmtPrint("[logic] LogicFriendModule::OnWLHandselRoseReq pPlayer is nullptr...charId:%llu", c2lHandselRoseReq.charid());
		return false;
	}

	Part *pPackage = pPlayer->GetPart(PART_PACKAGE);
	if (nullptr == pPackage)
	{
		LogErrFmtPrint("[logic] LogicFriendModule::OnWLHandselRoseReq pPackage part is nullptr charId=%lu", c2lHandselRoseReq.charid());
		HandselRoseRsp handselRoseRsp;
		handselRoseRsp.set_ret(RET_FAIL);
		pPlayer->SendDataToClient(EMODULE_ID_FRIEND, ProtoBuf::SERVER_TO_CLIENT_HANDSEL_ROSE, &handselRoseRsp);
		return false;
	}

	uint32_t itemId = c2lHandselRoseReq.item_id();
	uint32_t itemCount = c2lHandselRoseReq.item_count();
	const ItemItemCfgInfo *pItemCfg = g_GetItemItemCfgTable()->GetItemItemCfgInfo(itemId);
	if (nullptr == pItemCfg || pItemCfg->functionType != (int32_t)EItemFuncType::EItemFuncType_Rose)
	{
		HandselRoseRsp handselRoseRsp;
		handselRoseRsp.set_ret(RET_CONFIG_ERROR);
		pPlayer->SendDataToClient(EMODULE_ID_FRIEND, ProtoBuf::SERVER_TO_CLIENT_HANDSEL_ROSE, &handselRoseRsp);
		return false;
	}

	const VEC_INT32 *pvecPara = g_GetItemCfgMgr()->GetItemFuncParamCfg(itemId);
	if (nullptr == pvecPara || pvecPara->size() < 1)
	{
		HandselRoseRsp handselRoseRsp;
		handselRoseRsp.set_ret(RET_CONFIG_ERROR);
		pPlayer->SendDataToClient(EMODULE_ID_FRIEND, ProtoBuf::SERVER_TO_CLIENT_HANDSEL_ROSE, &handselRoseRsp);
		return false;
	}

/*
	LIST_ITEM removeItems;
	SItem item;
	item.nItemID = itemId;
	item.nNum = itemCount;
	removeItems.push_back(item);
	if (!pPackage->RemoveItem(removeItems, S_FRIEND))
	{
		HandselRoseRsp handselRoseRsp;
		handselRoseRsp.set_ret(RET_PACKAGE_ITEM_NOT_EXITS);
		pPlayer->SendDataToClient(EMODULE_ID_FRIEND, ProtoBuf::SERVER_TO_CLIENT_HANDSEL_ROSE, &handselRoseRsp);
		return false;
	}*/
	SItemSourceParam soureParam;
	soureParam.source = S_FRIEND;
	if (!pPackage->RemoveItem(itemId, itemCount, soureParam))
	{
		HandselRoseRsp handselRoseRsp;
		handselRoseRsp.set_ret(RET_PACKAGE_ITEM_NOT_EXITS);
		pPlayer->SendDataToClient(EMODULE_ID_FRIEND, ProtoBuf::SERVER_TO_CLIENT_HANDSEL_ROSE, &handselRoseRsp);
		return false;
	}

	uint32_t addCharm = pvecPara->at(0) * itemCount;
	L2CHandselRoseRsp l2cHandselRoseRsp;
	l2cHandselRoseRsp.set_ret(RET_SUCCESS);
	l2cHandselRoseRsp.set_type(c2lHandselRoseReq.type());
	l2cHandselRoseRsp.set_charm(addCharm);
	l2cHandselRoseRsp.set_charid(c2lHandselRoseReq.charid());
	l2cHandselRoseRsp.set_dst_char_id(c2lHandselRoseReq.dst_char_id());
	l2cHandselRoseRsp.set_item_name(pItemCfg->name);
	l2cHandselRoseRsp.set_item_count(itemCount);
	g_GetLogicService()->SendDataToCenter(EMODULE_ID_FRIEND, LOGIC_TO_CENTER_HANDSEL_ROSE, &l2cHandselRoseRsp);

	//pPackage->RemoveItem(cost.itemid(), cost.count(), S_FRIEND);

	return true;
}

bool LogicFriendModule::OnWLUpdateCharm(RECV_PACKAGE &package)
{
	ProtoBuf::C2LUpdateCharm c2lUpdateCharm;
	if (!c2lUpdateCharm.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		LogErrFmtPrint("[logic] OnWLUpdateCharm parse failed...");
		return false;
	}

	Player *pPlayer = g_GetCreatureMgr()->GetPlayer(c2lUpdateCharm.charid());
	if (nullptr == pPlayer)
	{
		LogErrFmtPrint("[logic] LogicFriendModule::OnWLUpdateCharm pPlayer is nullptr...charId:%llu", c2lUpdateCharm.charid());
		return false;
	}

	pPlayer->SetAttr(C_CHARM, c2lUpdateCharm.value(), true);
	return true;
}

bool LogicFriendModule::OnWLUpdateCloseness(RECV_PACKAGE &package)
{
	C2LUpdateCloseness updateCloseness;
	if (!updateCloseness.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		LogErrFmtPrint("[logic] OnWLUpdateCloseness parse failed...");
		return false;
	}

	Player *pPlayer = g_GetCreatureMgr()->GetPlayer(updateCloseness.charid());
	if (nullptr == pPlayer)
	{
		LogErrFmtPrint("[logic] LogicFriendModule::OnWLUpdateCloseness pPlayer is nullptr...charId:%llu", updateCloseness.charid());
		return false;
	}

	AchievementPart *pAchievePart = dynamic_cast<AchievementPart*>(pPlayer->GetPart(PART_ACHIEVEMENT));
	if (nullptr == pAchievePart)
	{
		LogErrFmtPrint("[logic] LogicFriendModule::OnWLUpdateCloseness pAchievePart is nullptr...charId:%llu", updateCloseness.charid());
		return false;
	}
	
	AchievementParameterInfo param;
	param.type = Update_Type_Total;
	param.parameterType = EAEventType_Camp_Union;
	param.parameter = PARAMETER_TYPE_CAMP_UNION_CLOSENESS;
	param.count = updateCloseness.value();
	pAchievePart->UpdateAchievement(param);

	return true;
}

void LogicFriendModule::OnTrackHateReq(CharIDType charId, RECV_PACKAGE &package)
{
	ProtoBuf::CWTrackHateReq req;
	ProtoBuf::WCTrackHateRsp rsp;
	if (!req.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		LogErrFmtPrint("[logic] CWTrackHateReq parse failed...");
		return;
	}

	Player *pPlayer = g_GetCreatureMgr()->GetPlayer(charId);
	if (nullptr == pPlayer)
	{
		LogErrFmtPrint("[logic] LogicFriendModule::OnTrackHateReq pPlayer is nullptr...charId:%llu", charId);
		return;
	}

	Part *pPackage = pPlayer->GetPart(PART_PACKAGE);
	if (nullptr == pPackage)
	{
		MMOLOG_FMT_DEBUG("[logic] LogicFriendModule::OnTrackHateReq pPackage part is nullptr charId=%lu", charId);
		return;
	}

	int32_t unBindCount = 0;
	int32_t nBindCount = 0;
	int32_t count = pPackage->GetItemNum(RELATION_TRACK_HATE_GOODID, unBindCount, nBindCount);
	if (count <= 0)
	{
		rsp.set_ret(RET_PACKAGE_ITEM_NUM_LACK);
		pPlayer->SendDataToClient(EMODULE_ID_FRIEND, ProtoBuf::SERVER_TO_CLIENT_TRACK_HATE, &rsp);
		return;
	}

	//玩家在特殊场景 禁止追踪
	if (pPlayer->GetScene()->IsUnion() || pPlayer->GetScene()->IsDynamic() || pPlayer->IsInJail() || nullptr != g_GetDuplicateMgr()->GetDuplicate(pPlayer->GetSceneId()))
	{
		rsp.set_ret(RET_RELATION_TRACK_HATE_ERROR);
		pPlayer->SendDataToClient(EMODULE_ID_FRIEND, ProtoBuf::SERVER_TO_CLIENT_TRACK_HATE, &rsp);
		return;
	}

	//如果追踪的仇恨玩家在同个逻辑节点
	CharIDType hateID = req.hatdid();
	Player *pHatePlayer = g_GetCreatureMgr()->GetPlayer(hateID);
	if (nullptr != pHatePlayer)
	{
		if (pHatePlayer->GetScene()->IsUnion() || pHatePlayer->GetScene()->IsDynamic() || pHatePlayer->IsInJail() || nullptr != g_GetDuplicateMgr()->GetDuplicate(pHatePlayer->GetSceneId()))
		{
			rsp.set_ret(RET_RELATION_TRACK_HATE_ERROR);
			pPlayer->SendDataToClient(EMODULE_ID_FRIEND, ProtoBuf::SERVER_TO_CLIENT_TRACK_HATE, &rsp);
			return;
		}

		uint32_t sceneId = pHatePlayer->GetSceneId();
		Point3<float> pos = pHatePlayer->GetPos();
		rsp.set_hatdid(hateID);
		rsp.set_sceneid(sceneId);
		Vector3PB* pCurpos = new Vector3PB();
		pCurpos->set_x(pos.x);
		pCurpos->set_y(pos.y);
		pCurpos->set_z(pos.z);
		rsp.set_allocated_dstpos(pCurpos);
		rsp.set_ret(RET_SUCCESS);
		pPlayer->SendDataToClient(EMODULE_ID_FRIEND, ProtoBuf::SERVER_TO_CLIENT_TRACK_HATE, &rsp);
		SItemSourceParam sourceParam;
		sourceParam.source = S_FRIEND;
		pPackage->RemoveItem(RELATION_TRACK_HATE_GOODID, 1, sourceParam);
		return;
	}

	//如果仇恨玩家不在同一个逻辑节点 通知中心服
	TrackHateReq toLogic;
	toLogic.set_charid(charId);
	toLogic.set_hateid(hateID);
	g_GetLogicService()->SendDataToCenter(EMODULE_ID_FRIEND, LOGIC_TO_CENTER_TRACK_HATE, &toLogic);
}
